package com.stormkai.reflect.demo2;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class ReflectDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//!执行create()方法前提是参数类有无参构造器
		Object obj = create("com.kevin.reflect.B");
		//reflect(obj);
		//System.out.println(getFieldValue(obj, "a"));
		Object mObj = call(obj, "add", new Class[]{int.class, Double.class}, new Object[]{2,3.5});
		System.out.println(mObj.toString());

	}
	
	/** 根据"类名"创建对象实例 */
	public static Object create(String className){
		
		try {
			//1.加载类
			//1.1在CLASSPATH中查找对应的类
			//1.2采用懒加载方式装载到内存
			Class cls = Class.forName(className);
			//2.创建类实例
			Object obj = cls.newInstance();
			return obj;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException("没搞定！", e);
		}
	}
	
	/**访问某对象的某属性*/
	public static Object getFieldValue(Object obj, String fieldName){
		
		try {
			//1.反射出类型
			Class cls = obj.getClass();
			//2.反射出类型字段
			Field field = cls.getDeclaredField(fieldName);
			//3.在对象obj上读取field属性的值
			Object val = field.get(obj);
			return val;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("没搞定", e);
		}
		
	}
	
	public static Object call(Object obj, String method, Class[] paramTypes, Object[] params){
		try {
			//1.发现类型
			Class cls = obj.getClass();
			//2.发现方法
			Method m = cls.getDeclaredMethod(method, paramTypes);
			//3.在对象obj调用方法m,传递参数类别params
			Object val = m.invoke(obj, params);
			return val;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("错误了！", e);
		}
	}
	
	/**
	 * 反射方法
	 * 用于实现
	 * 			obj 的类型是什么
	 * 			obj 有哪些属性
	 * 			obj 有哪些方法
	 * 			obj 有哪些构造器
	 * @param obj表示被反射的对象，被用于发现的对象
	 */
	public static void reflect(Object obj){
		//1.getClass()
		//	返回对象的类型，是Object类的方法
		Class cls = obj.getClass();
		System.out.println("类："+cls.getName());
		
		//2.getDeclaredFields()
		//	返回在类上声明的所有属性(字段)
		Field[] fields = cls.getDeclaredFields();
		System.out.println("属性：");
		for (Field field : fields) {
			System.out.println(
					field.getType()+":"+//属性类型
							field.getName());//属性名称
		}
		
		//3.getDeclaredMethods()
		//	返回在类上声明的所有方法
		Method[] methods = cls.getDeclaredMethods();
		System.out.println("方法：");
		for (Method method : methods) {
			System.out.print(method.getReturnType()+" ");
			System.out.print(method.getName()+" ");
			System.out.println(Arrays.toString(method.getParameterTypes()));
		}
		
		//4.getDeclaredConstructors()
		//	返回在类上声明的所有构造器
		Constructor[] constructors = cls.getDeclaredConstructors();
		System.out.println("构造器：");
		for (Constructor constructor : constructors) {
			System.out.print(constructor.getName()+" ");
			System.out.println(Arrays.toString(constructor.getParameterTypes()));
		}
		
	}

}

class B{
	int a = 3;
	public double add(int b, Double d){
		return a+b+d;
	}
}
